package br.edu.ifrn.potigol.lang;

import br.edu.ifrn.potigol.lang.ArgumentError;
import br.edu.ifrn.potigol.lang.Context;
import br.edu.ifrn.potigol.lang.Evaluable;
import br.edu.ifrn.potigol.lang.Method;
import br.edu.ifrn.potigol.lang.PotigolException;
import br.edu.ifrn.potigol.lang.PotigolObject;

/**
 * Método definido dentro de um script.
 */
public class InterpretedMethod extends Method {
  private String name;
  private Evaluable body;
  private String parameters[];
  
  /**
   * Cria um novo método.
   * @param name 		Nome do método.
   * @param parameters 	Lista de nomes dos parâmetros do método.
   * @param body 		Objeto a ser avaliado quando o método é chamado (normalmente um nó).
   */
  public InterpretedMethod(String name, String parameters[], Evaluable body) {
    this.name = name;
    this.parameters = parameters;
    this.body = body;
  }
  
  /**
   * Invoca e avalie o corpo do método.
   */
  public PotigolObject call(PotigolObject receiver, PotigolObject arguments[]) throws PotigolException {
	//Avalia o corpo do método no contexto do receptor
	Context context = new Context(receiver);

    if (parameters.length != arguments.length)
      throw new ArgumentError(name, parameters.length, arguments.length);
    
    //Coloca os argumentos em locals
    for (int i = 0; i < parameters.length; i++) {
      context.createLocal(parameters[i], arguments[i]);
    }

    return body.eval(context);
  }
}
